package com.bnzj.cloud.oauth2resource.ext;

import com.bnzj.cloud.oauth2resource.custom.CustomOauth2AuthenticationEntryPoint;
import com.bnzj.core.web.security.CustomAccessDeniedHandler;
import com.bnzj.core.web.security.CustomAuthenticationEntryPoint;
import com.bnzj.core.web.security.property.ResourcePathProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.stereotype.Component;

import java.util.Objects;

/**
 * @ClassName OauthResourceHttpSecurityAdapter
 * @Description 当使用oauth2 resource 认证方式时，用来暴露springSecurityFilter
 *              过滤链中相关配置给业务系统使用。
 * @Author
 * @Date 2020/2/27
 * @Version V1.0
 **/
@Component
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnMissingBean(name = "customResourceHttpSecurityAdapter")
public class OauthResourceHttpSecurityAdapter {

    @Autowired
    protected AuthenticationManager authenticationManager;

    @Autowired
    private ResourcePathProperties resourcePathProperties;

    @Autowired
    private CustomAccessDeniedHandler customAccessDeniedHandler;

    @Autowired
    private CustomAuthenticationEntryPoint customAuthenticationEntryPoint;

    @Autowired
    private CustomOauth2AuthenticationEntryPoint customOauth2AuthenticationEntryPoint;

    /**
     * @Description oauth resource 通用配置
     * @param http:
     * @return: void
     * @Author
     * @Date 2020/2/27
     **/
    public void config(HttpSecurity http) throws Exception{
        configBefore(http);
        String[] permitPaths = resourcePathProperties.getPermitPath();
        String[] authenticatedPaths = resourcePathProperties.getAuthenticatedPath();
        String[] verifyPaths = resourcePathProperties.getVerifyPath();
        http.cors().and().csrf().disable();

        //http.antMatcher("/api/idm/verify/*").authorizeRequests().antMatchers("/api/idm/verify/*").permitAll();
        if(!Objects.isNull(verifyPaths)){
            http.authorizeRequests().antMatchers(verifyPaths).access("@customAccessDecisionRule.check(authentication, request)");
        }
        if(!Objects.isNull(authenticatedPaths)){
            http.authorizeRequests().antMatchers(authenticatedPaths).authenticated();
        }
        if(!Objects.isNull(permitPaths)){
            http.authorizeRequests().antMatchers(permitPaths).permitAll();
        }
        http.oauth2ResourceServer().authenticationEntryPoint(customOauth2AuthenticationEntryPoint);
                http.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);

        http.exceptionHandling().accessDeniedHandler(customAccessDeniedHandler)
        .authenticationEntryPoint(customAuthenticationEntryPoint);
        http.authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll();
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        configAfter(http);
    }

    /**
     * @Description 子类重写做定制配置
     * @param http:
     * @return: void
     * @Author
     * @Date 2020/2/27
     **/
    protected void configBefore(HttpSecurity http) throws Exception{}

    /**
     * @Description 子类重写做定制配置
     * @param http:
     * @return: void
     * @Author
     * @Date 2020/2/27
     **/
    protected void configAfter(HttpSecurity http) throws Exception{
       http.authorizeRequests().anyRequest().permitAll();
    }

}
